Jak wywołać zdarzenie, gdy wartość zmiennej zostanie zmieniona?

Obecnie tworzę aplikację w C# przy użyciu Visual Studio. Chcę stworzyć jakiś kod tak, że gdy zmienna ma wartość 1, to pewien fragment kodu jest wykonywany. Wiem, że mogę użyć instrukcji if, ale problem polega na tym, że wartość zostanie zmieniona w procesie asynchronicznym, więc technicznie Instrukcja if może zostać zignorowana przed zmianą wartości.

Czy można utworzyć obsługę zdarzeń tak, aby gdy wartość zmiennej zmienia Zdarzenie jest uruchomiony? Jeśli tak, to jak Mogę to zrobić?

Jest całkowicie możliwe, że mogłem źle zrozumieć, jak działa oświadczenie if! Każda pomoc będzie mile widziana.

Author: Heinrich Ulbricht, 2011-04-30

6 answers

Wydaje mi się, że chcesz stworzyć nieruchomość.

public int MyProperty
{
    get { return _myProperty; }
    set
    {
        _myProperty = value;
        if (_myProperty == 1)
        {
            // DO SOMETHING HERE
        }
    }
}

private int _myProperty;

To pozwala na uruchomienie kodu za każdym razem, gdy wartość właściwości ulegnie zmianie. Możesz tu urządzić imprezę, jeśli chcesz.

 129
Author: Jonathan Wood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-23 23:32:53

Można użyć ustawiacza właściwości do wywołania zdarzenia za każdym razem, gdy wartość pola ma się zmienić.

Możesz mieć własnego delegata Eventhandlera lub możesz użyć słynnego systemu./ Align = "left" /

Zazwyczaj istnieje wzór na to:

  1. definiuje publiczne Zdarzenie za pomocą delegata obsługi zdarzenia (który ma argument typu EventArgs).
  2. Zdefiniuj chronioną metodę wirtualną o nazwie OnXXXXX (na przykład OnMyPropertyValueChanged). W tej metodzie można należy sprawdzić, czy delegat obsługi zdarzenia ma wartość null, a jeśli nie, można go wywołać(oznacza to, że do delegacji zdarzenia dołączona jest jedna lub więcej metod).
  3. wywołaj tę chronioną metodę, gdy chcesz powiadomić subskrybentów, że coś się zmieniło.

Oto przykład

private int _age;

//#1
public event System.EventHandler AgeChanged;

//#2
protected virtual void OnAgeChanged()
{ 
     if (AgeChanged != null) AgeChanged(this,EventArgs.Empty); 
}

public int Age
{
    get
    {
         return _age;
    }

    set
    {
         //#3
         _age=value;
         OnAgeChanged();
    }
 }

Zaletą tego podejścia jest to, że pozwalasz innym klasom, które chcą dziedziczyć z twojej klasy, zmienić zachowanie, jeśli to konieczne.

Jeśli chcesz złapać wydarzenie w inny wątek, który jest podnoszony musisz uważać, aby nie zmienić stanu obiektów zdefiniowanych w innym wątku, co spowoduje wyrzucenie wyjątku cross thread. Aby tego uniknąć, możesz użyć metody wywołania na obiekcie, który chcesz zmienić jego stan, aby upewnić się, że zmiana dzieje się w tym samym wątku, w którym zdarzenie zostało wywołane, lub w przypadku, gdy masz do czynienia z formularzem Windows, możesz użyć BackgourndWorker do robienia rzeczy w równoległym wątku spokojnie.

 69
Author: Beatles1692,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-15 19:33:56

. NET framework faktycznie zapewnia interfejs, który można użyć do powiadamiania subskrybentów, gdy właściwość uległa zmianie: System. ComponentModel.INotifyPropertyChanged. Interfejs ten posiada jedną właściwość eventową. Jest zwykle używany w WPF do wiązania, ale uznałem go za przydatny w warstwach biznesowych jako sposób standaryzacji powiadomienia o zmianie właściwości.

Jeśli chodzi o bezpieczeństwo wątku, włożyłbym zamek pod seterem, abyś nie biegał w żadnych warunkach wyścigowych.

Tutaj są moje myśli w kodzie:):

public class MyClass : INotifyPropertyChanged
{
    private object _lock;

    public int MyProperty
    {
        get
        {
            return _myProperty;
        }
        set
        {
            lock(_lock)
            {
                //The property changed event will get fired whenever
                //the value changes. The subscriber will do work if the value is
                //1. This way you can keep your business logic outside of the setter
                if(value != _myProperty)
                {
                    _myProperty = value;
                    NotifyPropertyChanged("MyProperty");
                }
            }
        }
    }

    private NotifyPropertyChanged(string propertyName)
    {
        //Raise PropertyChanged event
    }
    public event PropertyChangedEventHandler PropertyChanged;
}


public class MySubscriber
{
    private MyClass _myClass;        

    void PropertyChangedInMyClass(object sender, PropertyChangedEventArgs e)
    {
        switch(e.PropertyName)
        {
            case "MyProperty":
                DoWorkOnMyProperty(_myClass.MyProperty);
                break;
        }
    }

    void DoWorkOnMyProperty(int newValue)
    {
        if(newValue == 1)
        {
             //DO WORK HERE
        }
    }
}

Mam nadzieję, że to pomoże:)

 44
Author: Daniel Sandberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-30 21:13:47

Po prostu użyj właściwości

int  _theVariable;
public int TheVariable{
  get{return _theVariable;}
  set{
    _theVariable = value; 
    if ( _theVariable == 1){
      //Do stuff here.
    }
  }
}
 13
Author: Russell Troywest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-30 14:28:14

Możesz użyć klasy generycznej:

class Wrapped<T>  {
    private T _value;

    public Action ValueChanged;

    public T Value
    {
        get => _value;

        set
        {
            OnValueChanged();
            _value = value;
        }
    }

    protected virtual void OnValueChanged() => ValueChanged?.Invoke() ;
}

I będzie w stanie wykonać:

var i = new Wrapped<int>();

i.ValueChanged += () => { Console.WriteLine("changed!"); };

i.Value = 10;
i.Value = 10;
i.Value = 10;
i.Value = 10;

Console.ReadKey();

Wynik:

changed!
changed!
changed!
changed!
changed!
changed!
changed!
 2
Author: Andrew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-31 18:08:02

Prosta metoda polega na użyciu funkcji get I set na zmiennej


    using System;
    public string Name{
    get{
     return name;
    }
    
    set{
     name= value;
     OnVarChange?.Invoke();
    }
    }
    private string name;
    
    public event System.Action OnVarChange;

 1
Author: Namusanga Nicholas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-16 08:55:34